#include<iostream>
#include<assert.h>
#include<memory>
#include<mutex>
#include<functional>

// using namespace std;

//构造 + 析构 + (*重载) + (->重载)
// template<class T>
// class auto_ptr//拷贝时，被拷贝对象会将管理权转给拷贝对象。 隐患:悬空的对象可能会被误用
// {
// public:
//     auto_ptr(int count=int()):_ptr(new T(count)) {} //通过元素个数构造
//     auto_ptr(T* ptr):_ptr(ptr) {    ptr=nullptr;    } //通过指针构造

//     //拷贝构造，移交管理权
//     auto_ptr(auto_ptr& aptr)
//     :_ptr(aptr._ptr)/*两人同指向一块空间*/{
//         aptr._ptr=nullptr;
//     }

//     //赋值重载
//     auto_ptr<T>& operator=(auto_ptr& aptr){
//         _ptr=aptr._ptr;//两人同指向一块空间
//         aptr._ptr=nullptr;
//         return *this;
//     }

//     //* 运算符重载
//     T& operator*(){
//         return *_ptr;//可能会出现*(nullptr)的情况
//     }
//     //-> 运算符重载
//     T* operator->(){
//         return _ptr; //ap->push_back()
//     }
//     ~auto_ptr(){
//         cout<<"delete:"<<_ptr<<endl;
//         delete _ptr;
//     }
// public:
//     T* _ptr;
// };

// int main()
// {
//     auto_ptr<int> ap1(888);//new int(1) 是int*类型的变量  int的“构造” + auto_ptr的构造

//     auto_ptr<int> ap2(new int(2));
//     cout<<*ap1<<endl;
    
//     auto_ptr<int> ap3(ap1);//通过ap1构造ap3，即让ap1的指针指向ap3所管理的资源

//     cout<<*ap1<<endl;//由于在上一行的操作里，ap3的指针已经被置空了，此处再解引用的话就是*(nullptr)

//     return 0;
// }

// template <class T> struct default_delete {
//     constexpr default_delete() = default;
//     // template <class U> default_delete(const default_delete<U>&) noexcept {}
//     void operator()(T* ptr) const {
//         delete ptr;
//     }
// };

// template<class T,class D=default_delete<T>>//D默认是default_delete<T>类型
// class unique_ptr{//拷贝时，被拷贝对象会将管理权转给拷贝对象。 隐患:悬空的对象可能会被误用
// private:
//     T* _ptr;
//     D _delete;
// public:
//     unique_ptr(int count=int()):_ptr(new T(count)) {} //通过元素个数构造

//     //del默认是一个default_delete<T>类型的匿名对象
//     unique_ptr(T* ptr,D del=D()):_ptr(ptr),_delete(del) {    ptr=nullptr;    } //通过指针构造

//     //拷贝构造，移交管理权————禁掉
//     unique_ptr(const unique_ptr& aptr)=delete;
    
//     ~unique_ptr(){
//         _delete(_ptr);//通过default_delete<T>类型中的()运算符重载，实现对_ptr的特定式资源释放
//         _ptr=nullptr;
//     }

//     //赋值重载————禁掉
//     unique_ptr<T>& operator=(unique_ptr& aptr)=delete;

//     //* 运算符重载
//     T& operator*(){
//         return *_ptr;//可能会出现*(nullptr)的情况
//     }
//     //-> 运算符重载
//     T* operator->(){
//         return _ptr; //ap->push_back()
//     }

//     T* get() { return _ptr; }
//     void reset() { delete[] _ptr;  _ptr=nullptr; }
//     void swap(unique_ptr& uptr) { swap(_ptr,uptr._ptr); }
// };
// class A{
//     int _a;
// public:
//     A(int a=0):_a(a){   std::cout << "构造函数A()" << std::endl;    }

//     ~A(){    std::cout << "析构函数A()~" << std::endl;    }
// };
// template<class T>
// void deleteArray(T* ptr){//定制删除器——用来删除以特殊方式开辟的动态空间
//     std::cout << "deleteArray():" << std::endl;
//     delete[] ptr;
// }
// int main(){
//     unique_ptr<A> uptr0(new A(10)); //定义一个智能指针，指向存放一个A类型数据的堆空间  √

//     //unique_ptr<A> uptr1(new A[10]);//定义一个智能指针，指向存放10个A类型数据的堆空间   ×
//     //当系统对uptr1释放空间时，不会用默认的delete，而是回去调用deleteArray函数
//     unique_ptr<A,void(*)(A*)> uptr1(new A[10], deleteArray); //咱们自定义一个delete[]专门用来删除new[]开辟的空间
//     return 0;
// }

template<class T>//资源共享
class shared_ptr
{
private:
    T* _ptr;
    int* _pcount;//引用计数
    std::function<void(T*)> _delete;
public:
    // shared_ptr(T val=T()):_ptr(new T(val)),_pcount(new int(1)) {}

    template<class D>
    shared_ptr(T* ptr,D del=[](T* ptr){ delete ptr; }):_ptr(ptr),_pcount(new int(1)),_delete(del) {}

    // shared_ptr(T* ptr):_ptr(ptr),_pcount(new int(1)) {}

    //拷贝构造
    shared_ptr(const shared_ptr& sp){
        _ptr=sp._ptr;
        _pcount=sp._pcount;
        *(_pcount)++;
    }
    T& operator*(){
        assert(_ptr!=nullptr);
        return *_ptr;   
    }

    T* operator->(){  return _ptr;  }

    //赋值重载
    shared_ptr& operator=(const shared_ptr& sp){
        if(_ptr!=sp._ptr)
        {
            if(--*(_pcount)==0)
            {
                cout<<"delete _ptr and _pcount"<<endl;
                delete _ptr;
                delete _pcount;
            }
            _ptr=sp._ptr;
            _pcount=sp._pcount;
            *(_pcount)++;
        }
        return *this;
    }
    ~shared_ptr(){
        if(--*(_pcount)==0)
        {
            cout<<"delete _ptr"<<endl;
            _delete(_ptr);
            delete _pcount;
        }
    }
};

class A{
    int _a;
public:
    A(int a=0):_a(a){   std::cout << "构造函数A()" << std::endl;    }

    ~A(){    std::cout << "析构函数A()~" << std::endl;    }
};
template<class T>
void deleteArray(T* ptr){//定制删除器——用来删除以特殊方式开辟的动态空间
    std::cout << "deleteArray():" << std::endl;
    delete[] ptr;
}

int main()
{
    // shared_ptr<std::string> sp1("hello world"); //动态开辟一块空间，空间存放的数据是"hello world"
    // shared_ptr<std::string> sp2(sp1);           //用sp1拷贝构造sp2
    shared_ptr<A> sp3(new A(10),deleteArray<A>);   //动态开辟一块空间，空间存放的数据是"i am fine"

    // std::cout<<sp1->c_str()<<std::endl;              //通过->运算符重载，查看sp1指向的内容
    // std::cout<<*sp1<<std::endl;                      //通过*运算符重载，查看sp1指向的内容

    // sp2=sp3;                               //赋值操作，让sp2指向sp3所管理的动态资源，时sp2与sp3一同管理同一份资源
    // std::cout<<*sp3<<std::endl;                      //赋值后，sp3仍可以被操作
    return 0;
}

// template<class T>
// struct Node
// {
//     T val;//结点的具体值
//     shared_ptr<Node> next; //指向下一个结点的指针
//     shared_ptr<Node> prev; //指向前一个结点的指针
// };

// int main()
// {
//     shared_ptr<Node<int>> sp1(new Node<int>);
//     shared_ptr<Node<int>> sp2(new Node<int>);
//     sp1->next=sp2;//头结点的next指针指向第二个结点(此时，sp2所指向结点空间的引用计数为2)
//     sp2->prev=sp1;//第二个结点的prev指针指向头结点(此时，sp1所指向结点空间的引用计数为2)

//     //TODO

//     //当代码执行到这后，sp1和sp2都会调用析构函数，但这只会让它们指向空间的引用计数-=1，而不会进行资源释放，导致内存泄露~~
//     return 0;
// }

// class FileWrapper 
// {
// private:
//     FILE* file; //文件指针
// public:
//     //构造函数
//     FileWrapper(const char* filename, const char* mode) 
//     {
//         file = fopen(filename, mode);//在类的构造函数中打开文件
//         if (!file) { //处理打开文件失败的情况
//             cout<<"file open fail"<<endl;
//         }
//     }
//     ~FileWrapper() 
//     {
//         //在类的析构函数中关闭文件
//         if (file) {
//             fclose(file);
//         }
//     }
// };

// class LockWrapper {
// private:
//     std::mutex& mutex;
// public:
//     LockWrapper(std::mutex& m) : mutex(m) {
//         mutex.lock(); //完成加锁操作
//     }
//     ~LockWrapper() {
//         mutex.unlock(); //完成解锁操作
//     }
// };

// class Node {
// public:
//     std::shared_ptr<Node> next;
//     std::weak_ptr<Node> prev;
//     // 其他成员和方法
// };
// int main() {
//     std::shared_ptr<Node> node1(new Node());
//     std::shared_ptr<Node> node2(new Node());
//     node1->next = node2;
//     node2->prev = node1;
//     // 当离开main函数的作用域时，node1和node2的引用计数可以正常归零，对象被正确销毁
//     return 0;
// }

